<template>
  <div class="ad-template-media">
    <div class="title">
      {{ getProps.params.description }}
      <span v-if="getProps.params.required"> [必填]</span>
      <span v-else> [选填]</span>
    </div>
    <div v-if="error && !file" class="error">{{ errorMessage || `${getProps.params.description}不能为空` }}</div>

    <FUpload
      :params="uploadParams"
      :disabled="!!currentMaterial"
      @before-upload="beforeUpload"
      @progress="onProgress"
      @finish="onFinish"
      @error="onError"
    >
      <div v-if="isPercentage" class="percentage">
        <n-progress :stroke-width="16" :percentage="percentage" />
      </div>
      <!-- 预览-->
      <div v-else-if="file" class="preview-block">
        <div class="preview" :style="{ width: isVideo ? 'auto' : '180px' }">
          <video v-if="isVideo" ref="refVideo" :src="file" controls="controls" controlsList="nodownload" @click.stop />
          <n-image v-else :src="file" fit="cover" />
          <div v-if="!isVideo && !currentMaterial" class="preview-tips">
            <p>
<!--              <span>{{ entity.ratio_width }} : {{ entity.ratio_height }}</span>-->
              <span>{{ imageSize }}</span>
              <span>点击重新上传</span>
            </p>
          </div>
          <div v-if="!currentMaterial" class="tools-close" @click.stop="onClose">
            <x-icon class="iconfont icon-073" />
          </div>
        </div>
      </div>
      <!-- 转码等待-->
      <div v-else-if="isLoading" class="loading-block">
        <dl>
          <dd><i class="n-icon-loading" /></dd>
          <dt>{{ isVideo ? '视频转码中，请稍后...' : '图片智能截剪中' }}</dt>
        </dl>
      </div>
      <dl v-else class="f-upload-tips">
        <template v-if="isVideo">
          <dt v-if="[1334, 1536].some((s) => s === height)">9 : 16</dt>
<!--          <dt v-else>{{ width / divisorValue }} : {{ height / divisorValue }}</dt>-->
          <dd>
            <p>(推荐尺寸：{{ imageSize }})</p>
            <p>点击上传视频</p>
            <p
              >{{ fileFormat.join('/').toUpperCase() }}，{{ bytesToSize(entity.file_size) }} 时长≥{{
                entity.min_duration
              }}s，≤{{ entity.max_duration }}s，必须带有声音</p
            >
          </dd>
        </template>
        <template v-else>
          <dt>{{ imageSize }}</dt>
          <dd>
            <p>点击上传图片</p>
            <p>{{ fileFormat.join('/').toUpperCase() }}，{{ bytesToSize(entity.file_size) }}</p>
          </dd>
        </template>
        <dd v-if="isLibrary" class="tools">
          <x-button @click.stop="onShowDialog">从创意库选择</x-button>
        </dd>
      </dl>
    </FUpload>
    <!-- 创意库-->
    <div>
      <TemplateMediaSelect v-if="dialogParams.show" :modal-data="dialogParams" @change="onChangeMedia" />
    </div>
  </div>
</template>

<script setup lang="ts">
  import { useRoute, useRouter } from 'vue-router'
  import { XButton, XIcon } from '@/components'
  import { computed, reactive, ref, nextTick, onMounted, watch, defineExpose } from 'vue'
  import { NProgress, NImage, useMessage } from 'naive-ui'
  import { useStore } from '@/store'
  import { divisorValueFunction, bytesToSize } from '@/utils/index'
  import TemplateMediaSelect from '@/views/advertising/ads/create/components/step7/TemplateMediaSelect.vue'
  import FUpload from '@/views/advertising/ads/create/components/step7/FUpload.vue'

  const store = useStore()
  const router = useRouter()
  const route = useRoute()
  const message = useMessage()
  const props = defineProps({
    params: {
      type: Object,
      default: () => ({})
    },
    // 使用外部素材索引
    materialIndex: {
      type: Number,
      default: 0
    },
    // 使用外部素材
    material: {
      type: [Object, Array],
      default: () => []
    },
    // 是否允许使用外部素材
    isMaterial: {
      type: Boolean,
      default: false
    },
    // 是否允许从创意库选择
    isLibrary: {
      type: Boolean,
      default: true
    },
    // 是否为品牌标识
    isBrand: {
      type: Boolean,
      default: false
    }
  })
  const getProps = reactive(props)
  const emit = defineEmits(['change', 'durationchange'])
  const templateId = computed(() => {
    return store.state.intelligent.data.creative.templateId
  })
  const medias = computed(() => {
    return store.state.intelligent.data.creative.medias || []
  })
  const siteSet = computed(() => {
    return store.state.intelligent.data.position.siteSet
  })
  const accountCode = computed(() => {
    return store.state.intelligent.data.accountCode
  })
  const entity = computed(() => {
    let restriction
    switch (getProps.params.element_type) {
      case 'ELEMENT_TYPE_VIDEO':
        restriction = getProps.params.restriction.video_restriction
        break
      case 'ELEMENT_TYPE_IMAGE':
        restriction = getProps.params.restriction.image_restriction
        break
    }
    return restriction
  })
  const width = computed(() => {
    return entity.value.width || entity.value.min_width
  })
  const height = computed(() => {
    return entity.value.height || entity.value.min_height
  })
  // 最大公约数
  const divisorValue = computed(() => {
    return divisorValueFunction(width.value, height.value)
  })
  // 推荐尺寸
  const imageSize = computed(() => {
    return `${width.value}px X ${height.value}px`
  })
  // 文件格式
  const fileFormat = computed(() => {
    const type = {
      IMAGE_TYPE_JPG: '.jpg',
      IMAGE_TYPE_PNG: '.png',
      MEDIA_TYPE_MP4: '.mp4',
      MEDIA_TYPE_MOV: '.mov',
      MEDIA_TYPE_AVI: '.avi'
    }
    return entity.value.file_format.map((item: any) => {
      return type[item]
    })
  })
  // 是否为视频
  const isVideo = computed(() => {
    return getProps.params.name && getProps.params.name.includes('video')
  })
  // 是否展示上传进度
  const isPercentage = computed(() => {
    return percentage.value > 0 && percentage.value < 100
  })
  // 是否展示转换等待
  const isLoading = computed(() => {
    return percentage.value === 100 && !file.value && fileStatus.value !== 'finished'
  })
  // 当前使用外部素材的数据结构
  const currentMaterial = computed(() => {
    return getProps.material ? getProps.material[0] : null
  })
  const elVideo = ref()
  const dialogParams = ref({
    show: false,
    isVideo: false,
    width: width.value,
    height: height.value,
    pagination: {}
  })
  const file = ref()
  const fileStatus = ref('')
  const percentage = ref(0)
  const error = ref(false)
  const errorMessage = ref()
  const uploadParams = ref({
    mediaType: getProps.params.mediaType,
    resourceType: 0,
    accept: fileFormat.value.join(','),
    // 上传前校验规则
    rules: {
      ...entity.value,
      width: width.value,
      height: height.value,
      size: entity.value.file_size * 1024
    }
  })
  const refVideo = ref(null)

  onMounted(() => {
    if (getProps.params.default && !getProps.params.fileUrl) {
      const resourceType = /video/gi.test(getProps.params.name) ? 'video' : 'image'
      // this.$set(getProps.params, 'fileUrl', getResourceUrl(getProps.params.default, resourceType));
      getProps.params.fileUrl = getResourceUrl(getProps.params.default, resourceType)
      file.value = getResourceUrl(getProps.params.default, resourceType)
    }
  })

  watch(
    () => getProps.params.fileUrl,
    (val) => {
      // console.log(val)
      file.value = val
    },
    {
      immediate: true
    }
  )
  watch(
    () => currentMaterial.value,
    (val, oVal) => {
      replaceMaterial(val, oVal)
      // console.log('currentMaterial-change',val, oVal)
    },
    {
      immediate: true,
      deep: true
    }
  )
  function validate() {
    // 此处进行校验
    return new Promise((resolve, reject) => {
      // 校验是否必填
      if (getProps.params.required && !getProps.params.default) {
        error.value = true
        message.warning(`${getProps.params.description}不能为空`)
        return resolve(false)
      }
      error.value = false

      resolve({
        [getProps.params.name]: getProps.params.default
      })
    })
  }
  // 获取媒体资源预览地址
  function getResourceUrl(id, type) {
    const find = medias.value.find((item) => +item.mediaId === +id)
    if (find) {
      // 编辑状态下 signature 数据回填
      // this.$set(getProps.params, 'signature', find.signature)
      getProps.params.signature = find.signature
      return find.previewUrl
    } else {
      return `${process.env.VUE_APP_BASE_API}/ad/v2/resource/show?resourceType=${type}&accountId=${this.accountId}&resourceId=${id}`
    }
  }

  // 开始上传
  function beforeUpload() {
    onClose()
  }
  function onProgress(event) {
    // console.log(event)
    const multiple = Math.pow(10, 2)
    percentage.value = Math.round(event.file.percentage * multiple) / multiple
    fileStatus.value = event.file.status
  }
  // 上传成功
  function onFinish(res: any, fileBody: any) {
    // console.log('图片上传成功', res, fileBody)
    // 上传成功
    if (res.width === width.value && res.height === height.value && res.fileSize <= entity.value.file_size) {
      file.value = res.previewUrl
      getProps.params.default = String(res.mediaId)
      // this.$set(getProps.params, 'fileUrl', res.previewUrl)
      // this.$set(getProps.params, 'signature', res.signature)
      getProps.params.fileUrl = res.previewUrl
      getProps.params.signature = res.signature
      // 隐藏错误提示
      console.log('隐藏错误提示')
      error.value = false
      if (isVideo.value) {
        nextTick(() => {
          elVideo.value = refVideo.value
          fileStatus.value = 'finished'
          // emit('durationchange', onIsVideoDuration())
          emit('change', res)
          elVideo.value.addEventListener('durationchange', onIsVideoDuration())
        })
      }
    } else {
      onClose()
      message.warning(
        `素材尺寸、大小不符合要求；请选择${width.value}px X ${height.value}px、≤${bytesToSize(
          entity.value.file_size
        )}的素材`
      )
    }
  }
  function onError() {
    onClose()
  }
  // 清除
  function onClose() {
    // console.log('onClose', getProps.material)
    file.value = null
    percentage.value = 0
    if (getProps.params.default) {
      getProps.params.default = null
    }
    if (getProps.params.fileUrl) {
      getProps.params.fileUrl = null
    }
    if (getProps.params.signature) {
      getProps.params.signature = null
    }
  }
  // 显示创意库选择
  function onShowDialog() {
    dialogParams.value = {
      show: true,
      isVideo: isVideo.value,
      width: width.value,
      height: height.value,
      pagination: {
        actions: isVideo.value ? 'intelligent/getAdsVideoList' : 'intelligent/getAdsImageList',
        data: {
          accountCode: accountCode.value,
          width: width.value,
          height: height.value,
          size: entity.value.file_size
        }
      }
    }
  }
  // 从媒体库选择成功
  function onChangeMedia(item) {
    const { file_size } = entity.value
    if (item.width === width.value && item.height === height.value && item.fileSize <= file_size) {
      dialogParams.value.show = false
      getProps.params.default = String(item.mediaId)
      getProps.params.fileUrl = String(item.previewUrl)
      getProps.params.signature = String(item.signature)
      // this.$set(getProps.params, 'fileUrl', item.previewUrl);
      // this.$set(getProps.params, 'signature', item.signature);
      file.value = item.previewUrl
      // 隐藏错误提示
      error.value = false
      // 使用原生推广页不校验时长
      if (isVideo.value && !getProps.isMaterial) {
        nextTick(() => {
          elVideo.value = refVideo.value
          // emit('durationchange', onIsVideoDuration())
          elVideo.value.addEventListener('durationchange', onIsVideoDuration())
        })
      }
      emit('change', item)
    } else {
      message.warning(
        `素材尺寸、大小不符合要求；请选择${width.value}px X ${height.value}px、≤${bytesToSize(
          entity.value.file_size
        )}的素材`
      )
    }
  }
  // 校验视频时长
  function onIsVideoDuration() {
    console.log(elVideo.value, 1111111111)
    console.log(elVideo.value.duration, 2222)
    if (elVideo.value && elVideo.value.duration) {
      const duration = elVideo.value.duration
      console.log('当前视频时长为 ', duration)
      if (!(duration >= entity.value.min_duration && duration <= entity.value.max_duration)) {
        error.value = true
        file.value = null
        getProps.params.default = null
        getProps.params.fileUrl = null
        getProps.params.signature = null
        // this.$set(getProps.params, 'fileUrl', null);
        // this.$set(getProps.params, 'signature', null);
        errorMessage.value = `当前视频时长为：${duration}s，不符合要求, 应该为≥${entity.value.min_duration}s，≤${entity.value.max_duration}s, 请重新上传`
      }
    }
  }
  // 处理替换素材逻辑
  async function replaceMaterial(val, oVal) {
    if (currentMaterial.value) {
      let material
      if (currentMaterial.value.elementType === 'VIDEO') {
        const videoId = currentMaterial.value.videoSpecVideoId
        const { data } = await getMaterialInfo('video', videoId)
        material = data ? data[0] : null
      } else {
        const imageIdList = currentMaterial.value.imageSpecImageIdList
        const { data } = await getMaterialInfo('image', imageIdList)
        material = data ? data[0] : null
      }
      if (material) {
        onChangeMedia(material)
      }
    } else if (getProps.isMaterial.value && (val || oVal)) {
      // 初始化的时候不清除
      console.log('清空已经选择的素材数据')
      getProps.params.default = null
      // this.$set(getProps.params, 'fileUrl', null)
      // this.$set(getProps.params, 'signature', null)
      getProps.params.fileUrl = null
      getProps.params.signature = null
      file.value = null
    }
    // console.log(currentMaterial.value, 'currentMaterial', !!currentMaterial.value)
  }
  async function getMaterialInfo(type, mediaId) {
    if (mediaId) {
      return await store.dispatch(type === 'video' ? 'intelligent/getAdsVideoList' : 'intelligent/getAdsImageList', {
        accountCode: accountCode.value,
        mediaId
      })
    }
  }

  defineExpose({
    validate
  })
</script>

<style scoped lang="scss"></style>
